---
title: Add benchmarking to your pallet
slug: /how-to-guides/v3/weights/add-benchmarking
keywords: weights, benchmarking, runtime
version: '3.0'
section: how to guides
category: weights
---

<Objectives
  data={[
    {
      title: 'Goal',
      description:
        "Add [FRAME's benchmarking tool](/rustdocs/latest/frame_benchmarking/macro.benchmarks.html) to your pallet and write a simple benchmark.",
    },
    {
      title: 'Use Cases',
      description: `Setting up your pallet to be able to benchmark your extrinsics.`,
    },
    {
      title: 'Overview',
      description: `
        This guide steps throught the process of adding benchmarking to a pallet and runtime.
        In addition, it covers the steps of writing a simple benchmark for a pallet as well as testing and running the benchmarking tool.
        This guide does not cover updating weights with benchmarked values.
      `,
    },
  ]}
/>

## Steps

### 1. Set-up benchmarking for your pallet

1. In [the pallet's `Cargo.toml`](https://github.com/paritytech/substrate/blob/master/frame/example/Cargo.toml), add the `frame-benchmarking` crate (with appropriate tag and version) and the `runtime-benchmarks` feature.

   `pallets/example/Cargo.toml`

   ```toml
   [dependencies.frame-benchmarking]
   default-features = false
   git = 'https://github.com/paritytech/substrate.git'
   optional = true
   tag = '<monthly>'
   version = '<version>'

   [features]
   # -- snip --
   runtime-benchmarks = ["frame-benchmarking"]
   std = [
     # -- snip --
     'frame-benchmarking/std',
   ]
   ```

1. Create a new Rust module for your benchmarks in your pallet's folder (an example of [`/pallets/template/src/benchmarking.rs`](https://github.com/substrate-developer-hub/substrate-node-template/blob/latest/pallets/template/src/benchmarking.rs)), and create the basic structure:

   `pallets/example/src/benchmarking.rs`

   ```rust
    //! Benchmarks for Template Pallet
    #![cfg(feature = "runtime-benchmarks")]

    use crate::*;
    use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller};
    use frame_system::RawOrigin;

    benchmarks!{
      // Individual benchmarks are placed here
    }
   ```

1. Each benchmark case has up to three sections: a setup section, an execution section, and optionally a verification section at the end.

   ```rust
   benchmarks!{
     benchmark_name {
       /* setup initial state */
     }: {
       /* the code to be benchmarked */
     }
     verify {
       /* verifying final state */
     }
   }
   ```

   We'll refer to an extremely basic example of a benchmark from the [Example Pallet](https://github.com/paritytech/substrate/tree/master/frame/examples/basic).
   Take a look at the extrinsic we'll be benchmarking for:

   ```rust
   // This will measure the execution time of `set_dummy` for b in [1..1000] range.
   set_dummy {
     let b in 1 .. 1000;
   }: set_dummy(RawOrigin::Root, b.into());
   ```

   The name of the benchmark is `set_dummy`. Here `b` is a variable input that is passed into the extrinsic `set_dummy` which may affect the extrinsic execution time.
   `b` will be varied between 1 to 1,000, where we will repeat and measure the benchmark at the different values.

   In this example, the extrinsic `set_dummy` is called in the execution section, and we do not verify the result at the end.

1. Once you have written your benchmarks, you should make sure they execute properly by testing them.
   Add this macro at the bottom of your benchmarking module:

   `pallets/example/src/benchmarking.rs`

   ```rust
   impl_benchmark_test_suite!(
     YourPallet,
     crate::mock::new_test_ext(),
     crate::mock::Test,
   );
   ```

   The `impl_benchmark_test_suite!` macro takes three inputs: the Pallet struct generated by your pallet,
   a function that generates a test genesis storage (i.e. `new_text_ext()`), and a full runtime
   struct. These things you should get from your normal pallet unit tests.

   We will use your test environment and execute the benchmarks similar to how they would execute
   when actually running the benchmarks. If all tests pass, then it's likely that things will
   work when you actually run your benchmarks!

### 2. Add benchmarking to your runtime

With all the code completed on the pallet side, you need to also enable your full runtime to allow
benchmarking.

1. Update your runtime's `Cargo.toml` file to include the `runtime-benchmarking` features:

   ```toml
   [dependencies.pallet-you-created]
   default-features = false
   path = '../pallets/pallet-you-created'
   version = '3.0.0-monthly-2021-08'

   [features]
   runtime-benchmarks = [
     # -- snip --
     'pallet-you-created/runtime-benchmarks'
   ]
    std = [
     # -- snip --
     'pallet-you-created/std'
   ]
   ```

1. Add your new pallet to your runtime just as you would any other pallet.
   If you need more details check out the [Add a Pallet to Your Runtime Tutorial](/tutorials/v3/add-a-pallet) or [this guide on integrating a pallet to your runtime](/how-to-guides/v3/basics/pallet-integration).

1. Then, in addition to your normal runtime configuration, you also need to update the benchmarking section of your runtime.
   To add our new benchmarks, we simply add a new line with the `add_benchmark!` macro:

   ```rust
   #[cfg(feature = "runtime-benchmarks")]
   impl frame_benchmarking::Benchmark<Block> for Runtime {
     fn dispatch_benchmark(
       config: frame_benchmarking::BenchmarkConfig
     ) -> Result<(
       Vec<frame_benchmarking::BenchmarkBatch>,
       Vec<StorageInfo>),
       sp_runtime::RuntimeString,
       > {
         // -- snip --
         let whitelist: Vec<TrackedStorageKey> = vec![
           // You can whitelist any storage keys you do not want to track here
           ];
           let storage_info = AllPalletsWithSystem::storage_info();
           let mut batches = Vec::<BenchmarkBatch>::new();
           let params = (&config, &whitelist);

           // Adding the pallet for which you will perform the benchmarking
           add_benchmark!(params, batches, pallet_you_crated, YourPallet);

           // -- snip --

           if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
           Ok(batches, storage_info)
          }
      }
   ```

### 3. Run your benchmarks

1. Build your project with the benchmarks enabled:

   ```bash
   cargo build --release --features runtime-benchmarks
   ```

1. Once this is done, you should be able to run the `benchmark` subcommand from your project's top level directory to view all CLI options.
   This will also ensure that benchmarking has been properly integrated:

   ```bash
   ./target/release/node-template benchmark --help
   ```

The Benchmarking CLI has a lot of options which can help you automate your benchmarking.
Execute the following command to run standard benchmarking for your `pallet_you_created`:

```bash
./target/release/node-template benchmark \
    --chain dev \
    --execution wasm \
    --wasm-execution compiled \
    --pallet pallet_you_crated \
    --extrinsic '\*' \
    --steps 20 \
    --repeat 10 \
    --raw \
    --output ./pallets/src/pallet-created/weights.rs
```

This will create a `weights.rs` file inside your pallet's directory.
Refer to [this guide](/how-to-guides/v3/weights/use-benchmark-weights) to learn how to configure your pallet to use those weights.

## Examples

- [Benchmarking in the Example pallet](https://github.com/paritytech/substrate/blob/master/frame/examples/basic/src/benchmarking.rs)
- [Weights in the Example pallet](https://github.com/paritytech/substrate/blob/master/frame/examples/basic/src/weights.rs)

## Related material

#### Docs

- [Benchmarking](/v3/runtime/benchmarking)
- [Use custom weights from benchmarking](/how-to-guides/v3/weights/use-benchmark-weights)
